import { Scene } from '@babylonjs/core/scene';
import { AbstractControl, IAbstractControlOptions } from './abstract-control';
import { Control } from '@babylonjs/gui/2D/controls/control';
import { KeyPropertySet, VirtualKeyboard } from '@babylonjs/gui/2D/controls/virtualKeyboard';
import { StackPanel } from '@babylonjs/gui/2D/controls/stackPanel';
import { Vector3 } from '@babylonjs/core/Maths/math.vector';
import { UIInput } from './ui-input';
import { Button } from '@babylonjs/gui/2D/controls/button';


/**
 * ui软键盘控件参数对象
 * @param debug 调试绘制（仅开发中使用）
 * @param buttonBackground 按键背景颜色
 * @param fontColor 按键文字颜色
 * @param fontSize 按键文字字体大小
 * @param fontFamily 按键文字字体
 */
interface IUIKeyboardOptions extends IAbstractControlOptions {
    debug?: boolean
    buttonBackground?: string,
    fontColor?: string,
    fontSize?: number,
    fontFamily?: string,
}

/**
 * 按键信息对象
 * @param keys 按键键名集合
 * @param propertySets 按键属性对象集合
 */
interface IKeysInformation {
    keys: string[],
    propertySets?: KeyPropertySet[]
}


/**
 * ui软键盘控件
 * @param name 名称
 * @param scene 所在场景
 * @param options 参数对象
 */
class UIKeyboard extends AbstractControl {

    private _originalScale = new Vector3();
    private _tv0 = new Vector3();
    private _connected: UIInput | null = null;

    constructor(name: string, scene: Scene, options?: IUIKeyboardOptions) {
        super(name, scene, options);
        (this.control as VirtualKeyboard).children.forEach(child => {
            child.onPointerDownObservable.add(this.breakCamera);
            (child as StackPanel).children.forEach(c => c.onPointerDownObservable.add(this.breakCamera));
        });
    }

    /**
     * 获取连接到的输入控件
     */
    public get connected(): UIInput | null {
        return this._connected;
    }

    /**
     * 连接到输入控件
     * @param input 输入控件
     */
    public connect(input: UIInput | null): void {
        if (input) {
            (this.control as VirtualKeyboard).connect(input.input);
            this._connected = input;
        } else {
            (this.control as VirtualKeyboard).disconnect();
            this._connected = null;
        }
    }

    /**
     * 获取软键盘设置信息
     * @returns 软键盘设置信息
     */
    public getKeysRow(): IKeysInformation[] {
        return [
            { keys: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "=", "\u2190"] },
            { keys: ["q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "(", ")"] },
            { keys: ["a", "s", "d", "f", "g", "h", "j", "k", "l", ";", "'", "\u21B5"] },
            { keys: ["\u21E7", "z", "x", "c", "v", "b", "n", "m", ",", ".", "/", "?"] },
            {
                keys: ["+", "-", "*", "#", " ", ":", "<", ">", "!"],
                propertySets: [{}, {}, {}, {}, { width: "160px" }, {}, {}, {}, {}]
            }
        ];
    }

    protected initializeControl(name: string, scene: Scene, options: IUIKeyboardOptions): Control {
        const kb = new VirtualKeyboard(name + '-keyboard');
        const keysRow = this.getKeysRow();
        for (const kr of keysRow) {
            kb.addKeysRow(kr.keys, kr.propertySets);
        }

        if (options.debug) kb.background = '#ff00ff';
        kb.children.forEach(row => {
            (row as StackPanel).children.forEach(keyBtn => {
                const btn = keyBtn as Button;
                btn.color = options.fontColor || '#ffffff';
                btn.background = options.buttonBackground || '#000000';
                btn.fontSize = options.fontSize || 20;
                btn.fontFamily = options.fontFamily || 'Arial';
            });
        });
        kb.verticalAlignment = Control.VERTICAL_ALIGNMENT_CENTER;
        kb.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_CENTER;
        kb.transformCenterY = 0;
        kb.transformCenterX = 0.5;

        const w = this.width;
        const h = this.height;
        const rw = 7.5;
        const rh = 3.15;
        const ref = rh / rw;
        let s = h / w < ref ? h / rh : w / rw;
        kb.scaleY = s;
        kb.scaleX = s;

        return kb;
    }

    protected bindEvent(control: Control, options: IUIKeyboardOptions): void {
        (control as VirtualKeyboard).onIsVisibleChangedObservable.add((isVisible: boolean) => {
            const scl = this._tv0;
            if (!isVisible) {
                this._originalScale.copyFrom(this.container.scaling);
                scl.set(0, 0, 0);
            } else {
                scl.copyFrom(this._originalScale);
            }
            this.container.scaling.copyFrom(scl);
        });
    }

    protected unbindEvent(control: Control): void {
        super.unbindEvent(control);
        (control as VirtualKeyboard).onIsVisibleChangedObservable.clear();
    }

}


/**
 * 创建软键盘控件
 * @param name 名称
 * @param scene 所在场景
 * @param options 参数对象
 * @returns 软键盘控件
 */
const CreateUIKeyboard = (name: string, scene: Scene, options?: IUIKeyboardOptions): UIKeyboard => {
    const kb = new UIKeyboard(name, scene, options);
    return kb;
};


export { UIKeyboard, CreateUIKeyboard };
export type { IUIKeyboardOptions };